﻿using System;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Forms;
using System.Reactive.Disposables;
using CompositionalAudio.IO;
using CompositionalAudio;
using CompositionalAudio.Transforms;

namespace SoundCatcher
{
    public partial class FormMain : Form
    {
        private CompositionalAudio.CompositionalAudio compAudio = new CompositionalAudio.CompositionalAudio();


        private bool _isPlayer = true;  // audio output for testing
        private bool _isSaving = false;
        private bool _isShown = true;
        private string _sampleFilename;
        private DateTime _timeLastDetection;

        public FormMain()
        {
            InitializeComponent();
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            if (WaveInRecorder.DeviceCount == 0)
            {
                textBoxConsole.AppendText(DateTime.Now.ToString() + " : No audio input devices detected\r\n");
            }
            else
            {
                textBoxConsole.AppendText(DateTime.Now.ToString() + " : Audio input device detected\r\n");
                Start();
            }
        }

        
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            notifyIcon1.Visible = false;
            this.Visible = true;
            this.ShowInTaskbar = true;
            this.WindowState = FormWindowState.Normal;
            _isShown = true;
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void AmplitudeEvent()
        {
            toolStripStatusLabel1.Text = "Last event: " + _timeLastDetection.ToString();
        }
        private void FileSavedEvent()
        {
            textBoxConsole.AppendText(_timeLastDetection.ToString() + " : File " + _sampleFilename + " saved\r\n");
        }
        private void FormMain_SizeChanged(object sender, EventArgs e)
        {
            if (_isShown & this.WindowState == FormWindowState.Minimized)
            {
                foreach (Form f in this.MdiChildren)
                {
                    f.WindowState = FormWindowState.Normal;
                }
                this.ShowInTaskbar = false;
                this.Visible = false;
                notifyIcon1.Visible = true;
                _isShown = false;
            }
        }
        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Stop();
            if (_isSaving == true)
            {
                //Finish saving to file
                _isSaving = false;
            }
        }
        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormSettingsDialog form = new FormSettingsDialog();
            if (form.ShowDialog() == DialogResult.OK)
            {
                Stop();
                if (_isSaving == true)
                {
                    //Finish saving to file
                    _isSaving = false;
                }
                Start();
            }
        }
        private void Start()
        {
            Stop();
            try
            {
                var settings = Properties.Settings.Default;

                textBoxConsole.AppendText(DateTime.Now.ToString() + " : Audio input device polling started\r\n");
                textBoxConsole.AppendText(DateTime.Now + " : Device = " + settings.SettingAudioInputDevice.ToString() + "\r\n");
                textBoxConsole.AppendText(DateTime.Now + " : Channels = " + settings.SettingChannels.ToString() + "\r\n");
                textBoxConsole.AppendText(DateTime.Now + " : Bits per sample = " + settings.SettingBitsPerSample.ToString() + "\r\n");
                textBoxConsole.AppendText(DateTime.Now + " : Samples per second = " + settings.SettingSamplesPerSecond.ToString() + "\r\n");
                textBoxConsole.AppendText(DateTime.Now + " : Frame size = " + settings.SettingBytesPerFrame.ToString() + "\r\n");

                
                if (settings.SettingUseSigGen)
                {
                    compAudio.Source = new SignalGenerator(SignalGenerator.Sine, 100.0f, settings.SettingSigGenFreq, settings.SettingSamplesPerSecond);
                }
                else
                {
                    compAudio.Source = new WaveInRecorder(settings.SettingAudioInputDevice, settings.SettingSamplesPerSecond, settings.SettingBitsPerSample, settings.SettingChannels);
                }

                if (_isPlayer == true)
                {
                    compAudio.Output = new WaveOutPlayer(settings.SettingAudioOutputDevice, settings.SettingSamplesPerSecond, settings.SettingChannels);
                    compAudio.Connect(compAudio.Source.ToAudioSignal(512 * settings.SettingChannels, settings.SettingBitsPerSample), compAudio.Output);
                }


                var _waveLeft = compAudio.Source.ChannelLeft                   //left channel, stream of double[]
                                 .Buffer(settings.SettingBytesPerFrame); //buffer samples

                var _waveRight = compAudio.Source.ChannelRight
                                      .Buffer(settings.SettingBytesPerFrame);

                var _fftLeft = _waveLeft.FFT();
                var _fftRight = _waveRight.FFT();


                SpecLeft.GraphType = SpecRight.GraphType = DrawMethod.Spectrogram;
                SpecLeft.SampleRate = SpecRight.SampleRate = settings.SettingSamplesPerSecond;
                compAudio.Connect(_fftLeft,SpecLeft);
                compAudio.Connect(_fftRight,SpecRight);

                specFreqLeft.GraphType = specFreqRight.GraphType = DrawMethod.Freqency;
                specFreqLeft.SampleRate = specFreqRight.SampleRate = settings.SettingSamplesPerSecond;
                compAudio.Connect(_fftLeft,specFreqLeft);
                compAudio.Connect(_fftRight,specFreqRight);

                specTimeLeft.GraphType = specTimeRight.GraphType = DrawMethod.Time;
                specTimeLeft.SampleRate = specTimeRight.SampleRate = settings.SettingSamplesPerSecond;
                compAudio.Connect(_waveLeft,specTimeLeft);
                compAudio.Connect(_waveRight,specTimeRight);

                if (_isPlayer == true)
                    if (compAudio.Output != null)
                        compAudio.Output.Play();
                
            }
            catch (Exception ex)
            {
                textBoxConsole.AppendText(DateTime.Now + " : " + ex.InnerException.ToString() + "\r\n");
            }
        }
        private void Stop()
        {
            compAudio.Dispose();

            textBoxConsole.AppendText(DateTime.Now.ToString() + " : Audio input device polling stopped\r\n");
        }
    }
}